package com.yonyou.cyxdms.basedata.service.service.basedata;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yonyou.cms.channel.client.service.message.CmsChannelCommonService;
import com.yonyou.cyx.framework.util.bean.ApplicationContextHelper;
import com.yonyou.cyxdms.basedata.service.dto.SearchProductDlrDTO;
import com.yonyou.cyxdms.basedata.service.dto.SearchVsProductDlrDTO;
import com.yonyou.cyxdms.basedata.service.entity.basedata.ProductGroupPO;
import com.yonyou.cyxdms.basedata.service.repository.basedata.ProductGroupMapper;
import com.yonyou.cyxdms.basedata.service.vo.TreeVO;
import com.yonyou.cyxdms.basedata.service.vo.VsProductDlrVO;
import com.yonyou.cyxdms.framework.bean.dto.user_info.LoginInfoDto;
import com.yonyou.cyxdms.retail.client.dto.ProductGroupChildrenDTO;
import com.yonyou.cyxdms.retail.client.service.DlrProductService;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.util.*;

@Service
public class ProductGroupServiceImpl implements ProductGroupService {

    @Autowired
    private ProductGroupMapper productGroupMapper;

    @Autowired
    private DlrProductService dlrProductService;

    @Autowired
    private CmsChannelCommonService cmsChannelCommonService;

    private static final Logger logger = LoggerFactory.getLogger(ProductGroupServiceImpl.class);


    /**
     * 工具map
     */
    private Map<String,String> map  = new HashMap<String,String>(){
        {
            put("0","powerType");
            put("powerType","series");
            put("series","model");
            put("model","package");
            put("package","option");
            put("option","product");
        }
    };


    private Map<Integer,String> childrenMap = new HashMap<Integer,String>(){
        {
            put(6,"product");
            put(5,"option");
            put(4,"package");
            put(3,"model");
            put(2,"series");
            put(1,"powerType");
        }
    };
    @Override
    public List<TreeVO> tree(String optionCode, String productCode) {
        /**
         * 等级
         * 1 动力组成（车系同级的属性）
         * 2 车系
         * 3 车型
         * 4 配置
         * 5 12位选装
         * 6 18位整编（产品代码）
         */
        Map<String,List<TreeVO>> hierarchyMap = new HashMap<String,List<TreeVO>>(){
            {
                put("powerType",new ArrayList<>());
                put("series",new ArrayList<>());
                put("model",new ArrayList<>());
                put("package",new ArrayList<>());
                put("option",new ArrayList<>());
                put("product",new ArrayList<>());
            }
        };
        LoginInfoDto loginInfo = ApplicationContextHelper.getBeanByType(LoginInfoDto.class);
        //验重 map
        Map<String,String> check = new HashMap<>();
        //查询全部结果
        List<ProductGroupPO> list = productGroupMapper.queryList(optionCode,productCode,loginInfo.getAppId());
        logger.info("结果集为：{}",JSONObject.toJSONString(list));
        //迭代处理数据
        dispose("0",list,check,hierarchyMap);
        //迭代处理数据
        dispose(6,hierarchyMap);
        return hierarchyMap.get("powerType");
    }

    @Override
    public List<VsProductDlrVO> queryListByDlr(Page page, SearchVsProductDlrDTO searchVsProductDlrDTO){
        boolean flag = true;
        LoginInfoDto loginInfo = ApplicationContextHelper.getBeanByType(LoginInfoDto.class);
        String dealerCode = searchVsProductDlrDTO.getDealerCode();
        List<ProductGroupChildrenDTO> dtos = dlrProductService.queryListByDealerCode(dealerCode,loginInfo.getAppId());
        logger.info("产品组授权信息为"+JSONObject.toJSONString(dtos));
        SearchProductDlrDTO searchProductDlrDTO = new SearchProductDlrDTO();
        if(dtos != null && dtos.size() > 0){
            for(ProductGroupChildrenDTO dto : dtos){
                Integer level = dto.getLevel();
                String code = dto.getCode();
                String filedName = "level" + level ;
                setValue(searchProductDlrDTO,SearchProductDlrDTO.class,filedName+"Flag",Integer.class,1);
                List<String> list = (List<String>) getGetMethod(searchProductDlrDTO,filedName+"CodeList");
                list.add(code);
            }
            flag = false;
        }else {
            Map<String, List<Map<String, Object>>> map = cmsChannelCommonService.getNetInMessage(dealerCode,loginInfo.getAppId());
            logger.info("经销商入网授权信息为"+JSONObject.toJSONString(map));
            if(map != null){
                List<Map<String, Object>> authList = map.get("authList");
                List<Map<String, Object>> seriesList = map.get("seriesList");
                List<Map<String, Object>> modelList = map.get("modelList");
                if(modelList != null && modelList.size() > 0){
                    searchProductDlrDTO.setLevel3Flag(2);
                    for(Map<String,Object> entry : modelList){
                        searchProductDlrDTO.getLevel3IdList().add(Long.valueOf(entry.get("modelId").toString()));
                    }
                    flag = false;
                }
                if(seriesList != null && seriesList.size() > 0){
                    searchProductDlrDTO.setLevel2Flag(2);
                    for(Map<String,Object> entry : seriesList){
                        searchProductDlrDTO.getLevel2IdList().add(Long.valueOf(entry.get("seriesId").toString()));
                    }
                    flag = false;
                }
                if(authList != null && authList.size() > 0){
                    searchProductDlrDTO.setLevel1Flag(2);
                    for(Map<String,Object> entry : authList){
                        String value = entry.get("financeCompanyId").toString();
                        Integer type = null;
                        if("2".equals(value) ){
                            type = 60081001;
                        }else if("3".equals(value) || "4".equals(value)){
                            type = 60081002;
                        }
                        searchProductDlrDTO.getLevel1IdList().add(type);
                    }
                    flag = false;
                }
            }
        }
        if(flag){
            return null;
        }else {
            String brandProductList = searchVsProductDlrDTO.getBrandProductList();
            if(StringUtils.isNotBlank(brandProductList)){
                String[] idList = brandProductList.split(",");
                for(int i=0;i < idList.length;i++){
                    if("0".equals(idList[i])){
                        break;
                    }
                    if(i==0) {
                        searchVsProductDlrDTO.setBrandId(Long.parseLong(idList[i]));
                    }
                    if(i==1) {
                        searchVsProductDlrDTO.setSeriesId(Long.parseLong(idList[i]));
                    }
                    if(i==2) {
                        searchVsProductDlrDTO.setModelId(Long.parseLong(idList[i]));
                    }
                    if(i==3) {
                        searchVsProductDlrDTO.setPackageId(Long.parseLong(idList[i]));
                    }
                    if(i==4) {
                        searchVsProductDlrDTO.setOptionId(Long.parseLong(idList[i]));
                    }
                    if(i==5) {
                        searchVsProductDlrDTO.setColorId(Long.parseLong(idList[i]));
                    }
                }

            }
            searchVsProductDlrDTO.setAppId(loginInfo.getAppId());
            logger.info("授权信息为："+ JSONObject.toJSONString(searchProductDlrDTO));
            logger.info("搜索条件信息为："+ JSONObject.toJSONString(searchVsProductDlrDTO));
            List<VsProductDlrVO> vos = productGroupMapper.queryListVsProuct(page,searchVsProductDlrDTO,searchProductDlrDTO);
            return vos;
        }

    }

    @Override
    public VsProductDlrVO selectByProductCode(String productCode, String dealerCode,Integer powerType, String appId) {
        boolean flag = true;
        LoginInfoDto loginInfo = ApplicationContextHelper.getBeanByType(LoginInfoDto.class);
        List<ProductGroupChildrenDTO> dtos = dlrProductService.queryListByDealerCode(dealerCode,loginInfo.getAppId());
        SearchProductDlrDTO searchProductDlrDTO = new SearchProductDlrDTO();
        if(dtos != null && dtos.size() > 0){
            for(ProductGroupChildrenDTO dto : dtos){
                Integer level = dto.getLevel();
                String code = dto.getCode();
                String filedName = "level" + level ;
                setValue(searchProductDlrDTO,SearchProductDlrDTO.class,filedName+"Flag",Integer.class,1);
                List<String> list = (List<String>) getGetMethod(searchProductDlrDTO,filedName+"CodeList");
                list.add(code);
            }
            flag = false;
        }else {
            Map<String, List<Map<String, Object>>> map = cmsChannelCommonService.getNetInMessage(dealerCode,loginInfo.getAppId());
            if(map != null){
                List<Map<String, Object>> authList = map.get("authList");
                List<Map<String, Object>> seriesList = map.get("seriesList");
                List<Map<String, Object>> modelList = map.get("modelList");
                if(modelList != null && modelList.size() > 0){
                    searchProductDlrDTO.setLevel3Flag(2);
                    for(Map<String,Object> entry : modelList){
                        searchProductDlrDTO.getLevel3IdList().add(Long.valueOf(entry.get("modelId").toString()));
                    }
                    flag = false;
                }
                if(seriesList != null && seriesList.size() > 0){
                    searchProductDlrDTO.setLevel2Flag(2);
                    for(Map<String,Object> entry : seriesList){
                        searchProductDlrDTO.getLevel2IdList().add(Long.valueOf(entry.get("seriesId").toString()));
                    }
                    flag = false;
                }
                if(authList != null && authList.size() > 0){
                    searchProductDlrDTO.setLevel1Flag(2);
                    for(Map<String,Object> entry : authList){
                        String value = entry.get("financeCompanyId").toString();
                        Integer type = null;
                        if("2".equals(value) ){
                            type = 60081001;
                        }else if("3".equals(value) || "4".equals(value)){
                            type = 60081002;
                        }
                        searchProductDlrDTO.getLevel1IdList().add(type);
                    }
                    flag = false;
                }
            }
        }
        if(flag){
            return null;
        }else {
            VsProductDlrVO vo = productGroupMapper.selectByProductCode(productCode,appId,powerType,searchProductDlrDTO);
            return vo;
        }

    }

    /**
     * 处理数据 返回树状结构
     */
    private void dispose(Integer level,Map<String,List<TreeVO>> hierarchyMap){
        Integer nextLevel = level - 1;
        List<TreeVO> childrenList = hierarchyMap.get(childrenMap.get(level));
        List<TreeVO> parentList = hierarchyMap.get(childrenMap.get(nextLevel));
        for(TreeVO parent : parentList){
            parent.setLevel(nextLevel);
            if(parent.getChildren() == null){
                parent.setChildren(new ArrayList<TreeVO>());
            }
            for(TreeVO children : childrenList){
                children.setLevel(level);
                if(children.getParentId().equals(parent.getId())){
                    parent.getChildren().add(children);
                }
            }
        }
        if(nextLevel == 1){
            return;
        }
        dispose(nextLevel,hierarchyMap);
    }

    /**
     * 迭代方法 根据sql返回值 id是否为空 和 type类型 给返回vo赋值
     * @param type
     * @param list
     * @param check
     */
    private void dispose(String type,List<ProductGroupPO> list,Map<String,String> check,Map<String,List<TreeVO>> hierarchyMap){
        String currentType = map.get(type);
        for(ProductGroupPO po : list) {
            Object ob = null;
            if("0".equals(type)){
                ob = getGetMethod(po, currentType);
            }else {
                ob = getGetMethod(po,currentType+"Id");
            }
            if (ob != null) {
                if (!check.containsKey(currentType + ob.toString())) {
                    TreeVO vo = new TreeVO();
                    vo.setId(ob.toString());
                    vo.setId(ob.toString());
                    if ("0".equals(type)) {
                        vo.setName(ob.toString());
                        vo.setCode(ob.toString());
                    } else {
                        vo.setName(getGetMethod(po, currentType + "Name") == null ? null : getGetMethod(po, currentType + "Name").toString());
                        vo.setCode(getGetMethod(po, currentType + "Code") == null ? null : getGetMethod(po, currentType + "Code").toString());
                    }
                    if("0".equals(type)){
                        vo.setParentId("0");
                    } else if("powerType".equals(type)){
                        vo.setParentId(getGetMethod(po, type).toString());
                    }else {
                        vo.setParentId(getGetMethod(po, type+"Id").toString());
                    }
                    hierarchyMap.get(currentType).add(vo);
                    check.put(currentType + ob.toString(), "have");
                }
            }
        }
        if("product".equals(type)){
            return;
        }
        dispose(currentType,list,check,hierarchyMap);
    }

    /**
     * 获取指定类get方法
     * @param ob
     * @param name
     * @return
     */
    public static Object getGetMethod(Object ob , String name){
        try{
            Method[] m = ob.getClass().getMethods();
            for(int i = 0;i < m.length;i++){
                if(("get"+name).toLowerCase().equals(m[i].getName().toLowerCase())){
                    return m[i].invoke(ob);
                }
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 根据属性，拿到set方法，并把值set到对象中
     * @param obj 对象
     * @param clazz 对象的class
     * @param filedName 需要设置值得属性
     * @param typeClass
     * @param value
     */
    public static void setValue(Object obj,Class<?> clazz,String filedName,Class<?> typeClass,Object value){
        String methodName = "set" + filedName.substring(0,1).toUpperCase()+filedName.substring(1);
        try{
            Method method =  clazz.getDeclaredMethod(methodName, new Class[]{typeClass});
            method.invoke(obj, new Object[]{getClassTypeValue(typeClass, value)});
        }catch(Exception ex){
            ex.printStackTrace();
        }
    }

    /**
     * 通过class类型获取获取对应类型的值
     * @param typeClass class类型
     * @param value 值
     * @return Object
     */
    private static Object getClassTypeValue(Class<?> typeClass, Object value){
        if(typeClass == int.class  || value instanceof Integer){
            if(null == value){
                return 0;
            }
            return value;
        }else if(typeClass == short.class){
            if(null == value){
                return 0;
            }
            return value;
        }else if(typeClass == byte.class){
            if(null == value){
                return 0;
            }
            return value;
        }else if(typeClass == double.class){
            if(null == value){
                return 0;
            }
            return value;
        }else if(typeClass == long.class){
            if(null == value){
                return 0;
            }
            return value;
        }else if(typeClass == String.class){
            if(null == value){
                return "";
            }
            return value;
        }else if(typeClass == boolean.class){
            if(null == value){
                return true;
            }
            return value;
        }else if(typeClass == BigDecimal.class){
            if(null == value){
                return new BigDecimal(0);
            }
            return new BigDecimal(value+"");
        }else {
            return typeClass.cast(value);
        }
    }

}
